package com.sysu.minsysu.zdkb.utils;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

import android.R.integer;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.preference.Preference;
import android.text.format.Time;
import android.util.Log;
import android.widget.Toast;

public class CourseUtils {
	
	private static final String TAG = "CourseUtils";
	
	public static final String DEFAULTCLASSFILENAME = "classes.xml";

	private static final int termStartYear=2011;
	private static final int termStartMonth=9;
	private static final int termStartDay = 11;
	private static final int termEndYear=2012;
	private static final int termEndMonth=1;
	private static final int termEndDay = 13;

	//private static final String MAILADDRESS = "minsysu.course@gmail.com";
	private static final String TITLE = "title";
	private static final String DESCRIPTION = "description";
	private static final String EVENTLOCATION = "eventLocation";
	private static final String RRULE = "rrule";
	//private static final String ORGANIZER = "organizer";
	private static final String DTSTART = "dtstart";
	private static final String DURATION = "duration";
	private static final String HASALARM = "hasAlarm"; 
	private static final String DELETED = "deleted";
	
	private static final String PREF_COURSESETTING = "courseSetting";
	private static final String PREF_COURSECOUNT = "courseCount";
	private static final String PREF_COURSEIDPREFIX = "coursePrefix";
	
	private static String calenderURL = "";
	private static String calenderEventURL = "";
    private static String calenderRemiderURL = "";
    //为了兼容不同版本的日历,2.2以后url发生改变
	static{
		if(Integer.parseInt(Build.VERSION.SDK) >= 8){
			calenderURL = "content://com.android.calendar/calendars";
			calenderEventURL = "content://com.android.calendar/events";
			calenderRemiderURL = "content://com.android.calendar/reminders";

		}else{
			calenderURL = "content://calendar/calendars";
			calenderEventURL = "content://calendar/events";
			calenderRemiderURL = "content://calendar/reminders";		
		}
	}
	
	// true if conflict, else false;
	public static boolean checkConflicts( Course[] courses ) throws ClassTimeConflictException{
		for( int i=0; i<courses.length-1; i++ ){
			if( courses[i].conflictTest(courses[i+1])){
				throw new ClassTimeConflictException(courses[i], courses[i+1]);
			}
		}
		return false;
	}
	
	public static int getTermStartWeek(){
		Calendar calendar = Calendar.getInstance();
		calendar.set(termStartYear, termStartMonth, termStartDay);
		return calendar.get(Calendar.WEEK_OF_YEAR);
	}
	
	public static boolean isInThisTerm( Calendar c ){
		Calendar c1 = Calendar.getInstance();
		Calendar c2 = Calendar.getInstance();
		c1.set(termStartYear, termStartMonth, termStartDay);
		c2.set(termEndYear, termEndMonth, termEndDay);
		return  c.before(c2) && c.after(c1);
	}
	
	public static int delectExistingCourse( Context context, Course[] courses ){
		ContentResolver resolver = context.getContentResolver();
		int count=0;
		SharedPreferences preferences = context.getSharedPreferences(PREF_COURSESETTING, Activity.MODE_WORLD_WRITEABLE);
		SharedPreferences.Editor editor = preferences.edit();
		int courseCount = preferences.getInt(PREF_COURSECOUNT, 0);
		ArrayList<Long> preIds = new ArrayList<Long>();
		for( int i=0; i<courseCount; i++ ){
			preIds.add( preferences.getLong(PREF_COURSEIDPREFIX+i, 0) );
		}
		for( Course course : courses ){
			count += resolver.delete(Uri.parse( calenderEventURL ), "_id=" + course.getId(), null );
			for( int i=0; i<preIds.size(); i++ ){
				if( preIds.get(i) == course.getId() ){
					preIds.remove(i);
					break;
				}
			}
		}
		courseCount = preIds.size();
		for( int i=0; i<courseCount; i++ ){
			editor.putLong(PREF_COURSEIDPREFIX+i, preIds.get(i));
		}
		editor.putInt(PREF_COURSECOUNT, courseCount);
		editor.commit();
		return count;
	}

	public static boolean addNewCourses( Context context, Course[] courses, boolean exceptConflict ) throws ClassTimeConflictException{
		if( !exceptConflict ){
			try {
				checkConflicts(courses);
			} catch (ClassTimeConflictException e) {
				throw e;
			}
		}
		ContentResolver resolver = context.getContentResolver();
		String calId=null;
		Cursor userCursor = resolver.query(Uri.parse(calenderURL), null, null, null, null);
		if( userCursor.getCount()>0 ){
			userCursor.moveToFirst();
			calId = userCursor.getString(userCursor.getColumnIndex("_id"));
		}
		userCursor.close();
		
		SharedPreferences preferences = context.getSharedPreferences(PREF_COURSESETTING, Activity.MODE_WORLD_WRITEABLE);
		SharedPreferences.Editor editor = preferences.edit();
		int courseCount = preferences.getInt( PREF_COURSECOUNT, 0);
		for( Course course : courses ){
			ContentValues value = course2ContentValues(course);
			value.put("calendar_id", calId);
			
			Uri newEvent = resolver.insert( Uri.parse(calenderEventURL), value);
			long id = Long.parseLong( newEvent.getLastPathSegment() );
			ContentValues alertValues = new ContentValues();
			alertValues.put("event_id", id);
			alertValues.put("minutes", 10);
			
			resolver.insert( Uri.parse(calenderRemiderURL), alertValues);
//			Log.d(TAG, uri.getEncodedPath());
			editor.putLong( PREF_COURSEIDPREFIX + (courseCount++), Long.parseLong( newEvent.getLastPathSegment() ));
		}
		editor.putInt(PREF_COURSECOUNT, courseCount);
		editor.commit();
		return true;
	}
	
	
	
	public static ArrayList<Course> getSelectCourses( Context context, String fileName ){
		
		ArrayList<Course> res = new ArrayList<Course>();
		if( fileName==null )fileName = DEFAULTCLASSFILENAME;
		
		Course[] savedCourses = getSelectCoursesInCalendar(context);
		ArrayList<Course>[] courseLists = getClassTimetable(context, fileName);
		
		for( int k=0; k<savedCourses.length; k++ ){
			Course savedCourse = savedCourses[k];
			for( int i=0; i<4; i++ ){
				ArrayList<Course> tempCourseList = courseLists[i];
				for( Course course : tempCourseList ){
					if( savedCourse.equals(course) ){
						res.add(course);
					}
				}
			}
		}
		
		return res;
	}
	
	public static Course[] getSelectCoursesInCalendar( Context context ){
		
		
		SharedPreferences preferences = context.getSharedPreferences(PREF_COURSESETTING, Activity.MODE_WORLD_WRITEABLE);
		int courseCount = preferences.getInt(PREF_COURSECOUNT, 0);
		long[] courseIds = new long[courseCount];
		for( int i=0; i<courseCount; i++ ){
			courseIds[i] = preferences.getLong(PREF_COURSEIDPREFIX+i, 0);
		}
		
		ArrayList<Course> results = new ArrayList<Course>();

		Uri uri = Uri.parse(calenderEventURL);
		for( int i=0; i<courseCount; i++ ){
			Course course = new Course();
			Cursor cursor = context.getContentResolver().query(uri, null, "_id=" + courseIds[i], null, null);
			cursor.moveToFirst();
			course.setId( (int)cursor.getLong( cursor.getColumnIndex( "_id")));
			course.setCourseName( cursor.getString( cursor.getColumnIndex(TITLE)) );
			course.setTeacherName( cursor.getString( cursor.getColumnIndex(DESCRIPTION)) );
			Date date = new Date( cursor.getLong( cursor.getColumnIndex(DTSTART)));
			course.setDate( date.getDay()==0 ? 7 : date.getDay() );
			int hour = date.getHours();
			int minute = date.getMinutes();
			course.setTimeStart( (60*(hour-8)+minute)/55 );
			results.add( course );
		}
		
		Course[] r = new Course[results.size()];
		for( int i=0; i<results.size(); i++ )
			r[i] = results.get(i);
		results=null;
		return r;
	}
	
	
	private static ContentValues course2ContentValues(Course course){
		ContentValues event = new ContentValues();
		
		event.put(TITLE, course.getCourseName());
		event.put( DESCRIPTION, course.getTeacherName());
		event.put( EVENTLOCATION, course.getPlace());
		event.put( RRULE , getFreqString(course));
//		event.put( ORGANIZER, MAILADDRESS);
		
		Calendar calendar = Calendar.getInstance();
		Time time = classTimeConverter(course.timeStart);
		calendar.set(2011, termStartMonth-1, termStartDay+course.date, time.hour, time.minute);
		long start = calendar.getTime().getTime();
		event.put( DTSTART, start);
		
		int timelong = course.classCount * 45 -10 ;
		event.put( DURATION, "P" + timelong + "M");
		event.put( HASALARM, 1);
		
		return event;
	}
	
	public static Time[] getClassIntervalByClassTime( int startClass, int endClass){
		Time[] res = new Time[2];
		res[0] = classTimeConverter(startClass);
		res[1] = classTimeConverter(endClass, true);
		return res;
	}
	 
	public static Time classTimeConverter( int time, boolean end ){
		Time t = new Time();
		int minu = 55*time;
		if( end ) minu-=10;
		t.hour = 8+ minu/60;
		t.minute = minu%60;
		
		return t;
	}
	public static Time classTimeConverter( int time ){
		return classTimeConverter(time, false);
	}
	
	public static ArrayList<Course> getCourseWithTimeInterval( Context context, int week, int begin, int end){
		
		week-=getTermStartWeek();
		
		ArrayList<Course> res = new ArrayList<Course>();
		ArrayList<Course>[] lists = getClassTimetable(context, null);
		for( ArrayList<Course> list : lists ){
			for( Course course : list ){
				if( course.getWeekStart()<=week && course.getWeekLast() >= week 
						&& course.getTimeStart() >= begin && course.getTimeEnd() <= end)
					res.add(course);
			}
		}
		return res;
	}
	
	static String getFreqString( Course course ){
		//FREQ=WEEKLY;UNTIL=20110728T102959Z;WKST=SU;BYDAY=TH
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.append( "FREQ=WEEKLY;" );
		
		stringBuilder.append("BYDAY=");
		switch (course.date) {
		case 1:
			stringBuilder.append("MO");
			break;
		case 2:
			stringBuilder.append("TU");
			break;
		case 3:
			stringBuilder.append("WE");
			break;
		case 4:
			stringBuilder.append("TH");
			break;
		case 5:
			stringBuilder.append("FR");
			break;
		case 6:
			stringBuilder.append("SA");
			break;
		case 7:
			stringBuilder.append("SU");
			break;
		}
		stringBuilder.append( ";");
		
		stringBuilder.append("COUNT=" + course.getWeekLast() + ";");
		
		return stringBuilder.toString();
	}
	

	private static final String PUBLICCOURSES = "pubcourses";
	private static final String PUBLICELECTIVE = "pubelective";
	private static final String PROFESSIONALCOURSES = "procourses";
	private static final String PROFESSIONALELECTIVE = "proelective";
	private static final String CLASS = "class";
	private static final String COURSES = "courses";
	private static final String SCHOOL = "school";
	private static final String SHORTNAME = "sname";
	private static final String ID = "id";
	private static final String NAME = "name";
	private static final String TEACHER = "teacher";
	private static final String WEEKSTART = "weekstart";
	private static final String WEEKLAST = "weeklast";
	private static final String DATE = "date";
	private static final String TIMESTART = "timestart";
	private static final String CLASSCOUNT = "n";
	private static final String CAMPUS = "campus";
	private static final String BUILDING = "building";
	private static final String ROOMNUM = "room";
	
	public static ArrayList<Course>[] getClassTimetable( Context context, String fileName){
		if( fileName==null )
			fileName = DEFAULTCLASSFILENAME;
		ArrayList<Course>[] lists = new ArrayList[4];
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document=null;
			InputStream inputStream=null;
		
			inputStream = context.getAssets().open(fileName);
			document = builder.parse(inputStream);
			
			Element root = document.getDocumentElement();
			NodeList nodes = root.getElementsByTagName(COURSES);
			
			// public course
			lists[0] = getCoursesInNodeList( ((Element)nodes.item(0)).getElementsByTagName(CLASS));
			// public elective
			lists[1] = getCoursesInNodeList( ((Element)nodes.item(1)).getElementsByTagName(CLASS));
			
			lists[2] = new ArrayList<Course>();
			NodeList proCourseList = ( (Element)nodes.item(2)).getElementsByTagName(SCHOOL);
			for( int i=0; i<proCourseList.getLength(); i++ ){
				lists[2].addAll( getProCourseNodeInfo( (Element)proCourseList.item(i) ));
			}
			
			lists[3] = new ArrayList<Course>();
			NodeList proElectiveList = ( (Element)nodes.item(3)).getElementsByTagName(SCHOOL);
			for( int i=0; i<proElectiveList.getLength(); i++ ){
				lists[3].addAll( getProCourseNodeInfo( (Element)proElectiveList.item(i) ));
			}
			
			
		} catch (Exception e) {
			// TODO: handle exception
		}
		return lists;
	}
	
	static ArrayList<Course> getCoursesInNodeList( NodeList nodeList ){
		ArrayList<Course> list = new ArrayList<Course>();
		for( int i=0; i<nodeList.getLength(); i++ ){
			Element courseElement = (Element) nodeList.item(i);
			if( !courseElement.getNodeName().equals(CLASS))
				continue;
			
			Course course = getCourseNodeInfo(null, courseElement);
			
			list.add(course);	
		}
		return list;
	}
	
	static ArrayList<ProCourse> getProCourseNodeInfo( Element element ){
		ArrayList<ProCourse> list = new ArrayList<ProCourse>();
		
		String schooolName = element.getAttribute(NAME);
		int schoolID = Integer.parseInt( element.getAttribute(ID) );
		String shortName = element.getAttribute( SHORTNAME );
		
		NodeList childList = element.getElementsByTagName(CLASS);
		for( int i=0; i<childList.getLength(); i++ ){
			ProCourse course = new ProCourse();
			getCourseNodeInfo(course, (Element)childList.item(i));
			course.setSchoolID(schoolID);
			course.setSchoolName(schooolName);
			course.setSchoolShortName(shortName);
			
			list.add(course);
		}
		return list;
	}
	
	static Course getCourseNodeInfo( Course course, Element courseElement ){
		if( course==null )
			course = new Course();
		course.setId(Integer.parseInt(courseElement.getAttribute(ID)));
		course.setTeacherName(courseElement.getAttribute(TEACHER));
		course.setCourseName(courseElement.getAttribute(NAME));
		course.setCampus(courseElement.getAttribute(CAMPUS));
		course.setClassCount( Integer.parseInt(courseElement.getAttribute(CLASSCOUNT)));
		course.setDate( Integer.parseInt(courseElement.getAttribute(DATE)) );
		course.setBuilding( courseElement.getAttribute(BUILDING));
		course.setRoom(Integer.parseInt(courseElement.getAttribute(ROOMNUM)));
		course.setTimeStart( Integer.parseInt( courseElement.getAttribute(TIMESTART)) );
		course.setWeekLast( Integer.parseInt(courseElement.getAttribute(WEEKLAST)) );
		course.setWeekStart( Integer.parseInt(courseElement.getAttribute(WEEKSTART)) );
		
		return course;
	}
	
}
